#pragma once


#include <iostream>
#include <string>
#include <set>
#include <cstdio>
#include "Log.hpp"

const std::string sep = " ";
class Command
{
private:
    void LoadConf(const std::string& path)
    {
        //向内存中写 是In
        std::ifstream in(path.c_str());

        if(!in.is_open())
        {
            LOG(FATAL,"load conf error\n");
            exit(1);
        }

        //遍历文件，将字符串插入到set中
        std::string line;
        while(std::getline(in,line))
        {
            LOG(INFO,"--------%s\n",line.c_str());
            _safe_cmd.insert(line);

        }
        in.close();
    }
    std::string Precmd(std::string cmd)
    {
        //找一个命令的第一段
        if(cmd.empty()) return std::string();//空串

        auto pos = cmd.find(sep);
        if(pos == std::string::npos)
        {
            return cmd;
        }
        else
        {
            return cmd.substr(0,pos);
        }
        
    }
    bool isSafe(const std::string& cmd)
    {
        std::string precmd=Precmd(cmd);

        auto iter = _safe_cmd.find(precmd);
        if(iter == _safe_cmd.end())
        {
            return false;
        }
        return true;
        
    }
public:
    Command(std::string path):_conf_path(path)
    {
        LoadConf(_conf_path);
    }
    //执行命令
    std::string Execute(const std::string& cmd)
    {

        std::string result;
        if(isSafe(cmd))
        {
            //类似于myshell的逻辑，可以调用popen直接实现
            FILE* pipe_ptr = popen(cmd.c_str(),"r");
            if(pipe_ptr == nullptr)
            {
                LOG(FATAL,"open a pipe error\n");
                return "FILE* fail";
            }
            //由于TCP是面向字节流的，读取时，不一定一次就能读到全部
            //当前实验假设读取时能完整的读取
            char buffer[1024];
            while(fgets(buffer,sizeof(buffer),pipe_ptr) != NULL);
            {
                result += buffer;
            }
            pclose(pipe_ptr);
        }
        else
        {
            result = "非法命令\n";
        }
        return result;
    }
private:
    std::string _conf_path;
    std::set<std::string> _safe_cmd;
};